using System;
using System.IO;
using System.Collections;

namespace Copperline.Escriba
{
	/// <summary>
	/// Writes log events to a file
	/// </summary>
	public class FileLogger : LoggerBase
	{
		/// <summary>
		/// Creates an instance of the <c>FileLogger</c> class with a pathname
		/// </summary>
		/// <remarks>Set the PathName property before first use <see cref="PathName"/></remarks>
		public FileLogger()
		{
			Filter = new SeverityFilter( ESeverity.debug, ETrigger.threshold );
			Formatter = new TextFormatter();
			PathName = null;
		}

		/// <summary>
		/// Creates an instance of the <c>FileLogger</c> class with a pathname
		/// </summary>
		/// <remarks>If a portion of the directory part of the path does not
		/// exist, <c>FileLogger</c> attempts to create the necessary directory
		/// tree. If the file exists, logging events will append. Otherwise
		/// a new file is created.</remarks>
		/// <param name="path">the path of the file to create or append</param>
		public FileLogger( string path )
		{
			Filter = new SeverityFilter( ESeverity.debug, ETrigger.threshold );
			Formatter = new TextFormatter();
			PathName = path;
		}

		/// <summary>
		/// Creates an instance of the <c>FileLogger</c> class with complete
		/// specification of the file path, style, severity, and trigger
		/// </summary>
		/// <param name="path">the path of the file to create or append</param>
		/// <param name="severity">the minimum (or threshold) severity</param>
		/// <param name="trigger">specifies the trigger</param>
		public FileLogger( string path, ESeverity severity, ETrigger trigger )
		{
			Filter = new SeverityFilter( severity, trigger );
			Formatter = new TextFormatter();
			PathName = path;
		}

		private string sPathName;
		/// <summary>
		/// The full path to the file used for logging
		/// </summary>
		public string PathName
		{
			get { return this.sPathName; }
			set
			{
				Fault = false;
				LastError = null;
				Enabled = true;
				this.sPathName = value;
				if( this.sPathName == null || this.sPathName.Length == 0 )
				{
					Fault = true;
					LastError = new EscribaException("PathName cannot be null or empty");
				}

				else
				{
					try
					{
						FileInfo fi = new FileInfo( this.sPathName );
						if( !fi.Directory.Exists )
							fi.Directory.Create();

						if( fi.Exists )
						{
							switch( fi.Attributes )
							{
								case FileAttributes.Device:
									Fault = true;
									LastError = new EscribaException("Path '"+this.PathName+"' specifies a device");
									break;
								case FileAttributes.ReadOnly:
									Fault = true;
									LastError = new EscribaException("Path '"+this.PathName+"' is read only");
									break;
								default: break;
							}
						}

						else
						{
							if( fi.Attributes == FileAttributes.Directory )
							{
								Fault = true;
								LastError = new EscribaException("Path '"+this.PathName+"' is a directory");
							}
						}
					}

					catch( Exception ex )
					{
						Fault = true;
						LastError = new EscribaException("Cannot open '"+this.PathName+"' for logging", ex);
					}
				}
			}
		}

		/// <summary>
		/// Writes a LogEntry to the file
		/// </summary>
		/// <param name="logEntry">the LogEntry to write</param>
		public override void Write( LogEntry logEntry )
		{
			StreamWriter sw = new StreamWriter( PathName, true );
			Append( sw, logEntry );
			sw.Close();
		}
	}
}
